﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MasterDetailTemplate.Models;
using MasterDetailTemplate.Services;
using Xamarin.Forms;
using Xamarin.Forms.Extended;

namespace MasterDetailTemplate.ViewModels
{
    /// <summary>
    /// 查询页ViewModel。
    /// By FJH
    /// </summary>
    public class SearchPageViewModel : ViewModelBase,INotifyPropertyChanged
    {
        /// <summary>
        /// 能否加载更多结果。
        /// </summary>
        private bool _canLoadMore;

        /// <summary>
        /// 内容导航服务接口。
        /// </summary>
        IContentNavigationService _contentNavigationService;

        /// <summary>
        /// 根导航。
        /// </summary>
        private IRootNavigationService _rootNavigationService;

        /// <summary>
        /// 事件存储。
        /// </summary>
        private IEventStorage _eventStorage;

        /// <summary>
        /// 事件集合。
        /// </summary>
        private InfiniteScrollCollection<Event> eventCollection;

        /// <summary>
        /// 事件集合。
        /// </summary>
        public InfiniteScrollCollection<Event> EventCollection
        {
            get { return eventCollection; }
            set
            {
                eventCollection = value;
                NotifyPropertyChanged();
            }
        }

        public Event Event
        {
            get => _event;
            set => Set(nameof(Event), ref _event, value);
        }

        private Event _event;

        /// <summary>
        /// 查询页ViewModel构造函数。
        /// </summary>
        /// <param name="contentNavigationService">内容导航服务接口。</param>
        /// <param name="rootNavigationService">根导航服务接口。</param>
        /// <param name="eventStorage">事件存储。</param>
        public SearchPageViewModel(IContentNavigationService contentNavigationService,
            IRootNavigationService rootNavigationService,
            IEventStorage eventStorage)
        {
            _contentNavigationService = contentNavigationService;
            _rootNavigationService = rootNavigationService;
            _eventStorage = eventStorage;

            Where = Expression.Lambda<Func<Event, bool>>(
                Expression.Constant(true),
                Expression.Parameter(typeof(Event), "e"));

            EventCollection = new InfiniteScrollCollection<Event>();
            EventCollection.OnCanLoadMore = () => _canLoadMore;
            EventCollection.OnLoadMore = async () =>
            {
                Status = Loading;
                var events =
                    await eventStorage.GetEventsAsync(Where,
                        EventCollection.Count, PageSize);
                Status = string.Empty;
                if (events.Count < PageSize)
                {
                    _canLoadMore = false;
                    Status = NoMoreResult;
                }
                if (EventCollection.Count == 0 && events.Count == 0)
                {
                    Status = NoResult;
                }
                return events;
            };
        }

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        public RelayCommand _pageAppearingCommand;

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        public RelayCommand PageAppearingCommand =>
            _pageAppearingCommand ?? (_pageAppearingCommand =
                new RelayCommand(async () =>
                {
                    await PageAppearingCommandFunction();
                }));

        /// <summary>
        /// 页面显示命令函数。
        /// </summary>
        public async Task PageAppearingCommandFunction()
        {
            EventCollection.Clear();
            _canLoadMore = true;
            await EventCollection.LoadMoreAsync();
        }

        /// <summary>
        /// 查询语句。
        /// </summary>
        public Expression<Func<Event, bool>> Where
        {
            get => _where;
            set
            {
                _where = value;
            }
        }

        /// <summary>
        /// 查询语句。
        /// </summary>
        private Expression<Func<Event, bool>> _where;

        /// <summary>
        /// 属性改变变量。
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 监控属性改变函数。
        /// </summary>
        /// <param name="propertyName">属性名</param>
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 查询命令。
        /// </summary>
        public ICommand QueryCommand =>
            _queryCommand ?? (_queryCommand =
                new Command<string>(async (string query) => 
                    QueryCommandFunction(query)));


        /// <summary>
        /// 查询命令。
        /// </summary>
        private Command _queryCommand;

        public async Task QueryCommandFunction(string query)
        {
            EventCollection.Clear();
            _canLoadMore = true;

            ParameterExpression parameter = Expression.Parameter(typeof(Event), "e");
            MemberExpression member = Expression.PropertyOrField(parameter, "Title");
            MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            ConstantExpression constant = Expression.Constant(query, typeof(string));
            Where = Expression.Lambda<Func<Event, bool>>(Expression.Call(member, method, constant), parameter);

            EventCollection = new InfiniteScrollCollection<Event>();
            EventCollection.OnCanLoadMore = () => _canLoadMore;
            EventCollection.OnLoadMore = async () =>
            {
                Status = Loading;
                var events =
                    await _eventStorage.GetEventsAsync(Where,
                        EventCollection.Count, PageSize);
                Status = string.Empty;
                if (events.Count < PageSize)
                {
                    _canLoadMore = false;
                    Status = NoMoreResult;
                }
                if (EventCollection.Count == 0 && events.Count == 0)
                {
                    Status = NoResult;
                }
                return events;
            };
            if (Status != NoResult)
            {
                EventCollection.LoadMoreAsync();
            }
            else
            {
                Status = string.Empty;
            }
        }

        /// <summary>
        /// 点击事件命令。
        /// </summary>
        public RelayCommand<Event> EventTappedCommand =>
            _eventTappedCommand ?? (_eventTappedCommand =
                new RelayCommand<Event>(async @event =>
                    await EventTappedCommandFunction(@event)));

        /// <summary>
        /// 点击事件命令。
        /// </summary>
        private RelayCommand<Event> _eventTappedCommand;

        internal async Task EventTappedCommandFunction(Event eEvent) =>
            await _contentNavigationService.NavigateToAsync(
                ContentNavigationConstants.AnniversaryDetailPage, eEvent);

        /// <summary>
        /// 收藏点击功能。
        /// </summary>
        private RelayCommand<Event> _stickDayCommand;

        /// <summary>
        /// 收藏点击功能。
        /// </summary>
        public RelayCommand<Event> StickDayCommand =>
            _stickDayCommand ?? (_stickDayCommand =
                new RelayCommand<Event>(async @event =>
                    await StickDayCommandFunction(@event)));

        public async Task StickDayCommandFunction(Event eEvent)
        {
            if (eEvent.IsImportant == 1)
            {
                eEvent.IsImportant = 0;
            }
            else
            {
                eEvent.IsImportant = 1;
            }

            eEvent.DateStamp = DateTime.Now.Ticks;
            await _eventStorage.SaveEventAsync(eEvent);
        }

        /// <summary>
        /// 事件删除。
        /// </summary>
        public RelayCommand<Event> DeleteCommand =>
            _deleteCommand ?? (_deleteCommand =
                new RelayCommand<Event>(async @event =>
                    await DeleteCommandFunction(@event)));

        private RelayCommand<Event> _deleteCommand;

        public async Task DeleteCommandFunction(Event eEvent)
        {
            await _eventStorage.DeleteEventAsync(eEvent);
            EventCollection.Clear();
            _canLoadMore = true;
            await EventCollection.LoadMoreAsync();
        }

        /// <summary>
        /// 加载状态。
        /// </summary>
        public string Status
        {
            get => _status;
            set
            {
                _status = value;
            }
        }

        /// <summary>
        /// 加载状态。 
        /// </summary>
        private string _status;

        /// <summary>
        /// 正在载入。
        /// </summary>
        public const string Loading = "正在载入";

        /// <summary>
        /// 没有满足条件的结果。
        /// </summary>
        public const string NoResult = "没有满足条件的结果";

        /// <summary>
        /// 没有更多结果。
        /// </summary>
        public const string NoMoreResult = "没有更多结果";

        /// <summary>
        /// 一次显示的诗词数量。
        /// </summary>
        public const int PageSize = 20;

    }
}
